/**
 * -----------------------------------------------------------------------------
 * 	Copyright  Faraday Technology Corp 2010-2014.  All rights reserved.
 * -----------------------------------------------------------------------------
 * FILENAME:  ftsdc021.h
 * DEPARTMENT :CTD/SD
 * VERSION: Revision:1.0
 * -----------------------------------------------------------------------------
 *  MAJOR REVISION HISTORY
 *  DATE        AUTHOR       	 DESCRIPTION
 * 2009/12//	Mike Yeh	 Original FTSDC020 code
 * 2010/4/2	BingJiun-Luo	 FTSDC021 code	
 * -----------------------------------------------------------------------------
 */

#ifndef FTSDC021_H
#define FTSDC021_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//#include "SoFlexible.h"
//#include "fat.h"
#define IPMODULE SDC
#define IPNAME FTSDC021

//#include "ftsdc021_mmc.h"

#define FTSDC021_VERSION	"001.201704"

#define TIMER_HZ		1000

#define	CMDLEN			50
#define	MAXARGS			20

#ifndef	isblank
#define	isblank(ch)	(((ch) == ' ') || ((ch) == '\t'))
#endif
#define FREE_MEM_BASE 0x83000000
/**
 * Descriptor Table used for ADMA2 transfer.
 * One descriptor line consumes 8 bytes and can transfer
 * maximum 65536 bytes. Default ADMA2_NUM_OF_LINES is 
 * 1536. 
 */
#define ADMA2_DESC_TABLE    FREE_MEM_BASE	
#define ADMA2_NUM_OF_LINES	1536

#define FTSDC021_DMA_LLD_STRUCT_ADDR (ADMA2_DESC_TABLE + (ADMA2_NUM_OF_LINES << 3))
/* Assume MAx read write sectors is 16 MBytes.
 * Max LLD structure need is (0x1000000 + 4079)/4080 = approx 4000.
 * Each LLD structure is 16 bytes x 4000 = 64000(0xFA00) bytes.(total memory we need)
 * More 4096 bytes of write buffer for packed commands header.   
 */

#define FTSDC021_BUFFER_END    (FREE_MEM_BASE+0x2000000)
#define FTSDC021_WRITE_BUFFER	(FTSDC021_DMA_LLD_STRUCT_ADDR + 0xFA00)
#define FTSDC021_BUFFER_LENGTH	((FTSDC021_BUFFER_END - FTSDC021_WRITE_BUFFER) >> 1)
#define FTSDC021_READ_BUFFER	(FTSDC021_WRITE_BUFFER + FTSDC021_BUFFER_LENGTH)

#define FTSDC021_DEF_BLK_LEN	0x200
#define FTSDC021_BASE	SDC_FTSDC021_PA_BASE
#define FTSDC021_IRQ	SDC_FTSDC021_IRQ

#define SDHCI_FILESYSTEM_MODE	0

#define SDHCI_INFINITE_TRANSFER	0
#if (SDHCI_INFINITE_TRANSFER)
#define SYNC_ABORT		0
#endif

#define Standard_Capacity	0
#define Normal_Capacity		1
#define High_Capacity		2

#define FIFO_depth_4_words	0
#define FIFO_depth_8_words	1
#define FIFO_depth_16_words	2
#define FIFO_depth_128_words	3
#define FIFO_depth_256_words	4
#define FIFO_depth_512_words	5

#define CARD_TYPE_UNKNOWN	0
#define MEMORY_CARD_TYPE_SD	1
#define MEMORY_CARD_TYPE_MMC	2
#define SDIO_TYPE_CARD		3
#define MEMORY_SDIO_COMBO	4
#define MEMORY_eMMC		5

/* For SD Memory Register (unit of byte) */
#define SCR_LENGTH		8
#define SD_WRITTEN_NUM_LENGTH   4
#define SD_STATUS_LENGTH	64

/* For MMC Memory Register */
#define EXT_CSD_LENGTH		512
typedef	unsigned long long	UINT64;
typedef	unsigned int		UINT32;
typedef	int					INT32;
typedef	unsigned short		UINT16;
typedef	short				INT16;
typedef unsigned char		UINT8;
typedef char				INT8;
typedef unsigned char		BOOL;

typedef struct {
	UINT32 SdmaAddr;	// 0x00-0x03
	UINT16 BlkSize;		// 0x04-0x05
	UINT16 BlkCnt;		// 0x06-0x07
	UINT32 CmdArgu;		// 0x08-0x0B
	UINT16 TxMode;		// 0x0C-0x0D
	UINT16 CmdReg;		// 0x0E-0x0F
	UINT64 CmdRespLo;	// 0x10-0x17
	UINT64 CmdRespHi;	// 0x18-0x1F
	UINT32 BufData;		// 0x20-0x23
	UINT32 PresentState;	// 0x24-0x27
	UINT8 HCReg;		// 0x28
	UINT8 PowerCtl;		// 0x29
	UINT8 BlkGapCtl;	// 0x2A
	UINT8 WakeUpCtl;	// 0x2B
	UINT16 ClkCtl;		// 0x2C-0x2D
	UINT8 TimeOutCtl;	// 0x2E
	UINT8 SoftRst;		// 0x2F
	UINT16 IntrSts;		// 0x30-0x31
	UINT16 ErrSts;		// 0x32-0x33
	UINT16 IntrEn;		// 0x34-0x35
	UINT16 ErrEn;		// 0x36-0x37
	UINT16 IntrSigEn;	// 0x38-0x39
	UINT16 ErrSigEn;	// 0x3A-0x3B
	UINT16 AutoCMDErr;	// 0x3C-0x3D
	UINT16 HostCtrl2;	// 0x3E-0x3F
	UINT32 CapReg;		// 0x40-0x43
	UINT32 CapReg2;		// 0x44-0x47
	UINT64 MaxCurr;		// 0x48-0x4F
	UINT16 CMD12ForceEvt;	// 0x50-0x51
	UINT16 ForceEvt;	// 0x52-0x53
	UINT32 ADMAErrSts;	// 0x54-0x57
	UINT64 ADMAAddr;	// 0x58-0x5F
	/*
	 *  Register offset 0x60 - 0x6F change at FTSDC021
	 */
	UINT16 PresetValInit;	// 0x60-0x61
	UINT16 PresetValDS;	// 0x62-0x63
	UINT16 PresetValHS;	// 0x64-0x65
	UINT16 PresetValSDR12;	// 0x66-0x67
	UINT16 PresetValSDR25;	// 0x68-0x69
	UINT16 PresetValSDR50;	// 0x6A-0x6B
	UINT16 PresetValSDR104;	// 0x6C-0x6D
	UINT16 PresetValDDR50;	// 0x6E-0x6F

	UINT32 Reserved[28];	// 0x70-0xDF
	UINT32 ShareBusCtrl;	// 0xE0-0xE3
	UINT32 Reserved2[6];	// 0xE4-0xFB
	UINT16 SltIntrSts;	// 0xFC-0xFD
	UINT16 HCVer;		// 0xFE-0xFF
	UINT32 VendorReg0;	// 0x100-0x103
	UINT32 VendorReg1;	// 0x104-0x107
	UINT32 VendorReg2;	// 0x108-0x10B
	UINT32 VendorReg3;	// 0x10C-0x10F
	UINT32 VendorReg4;	// 0x110-0x113
	UINT32 VendorReg5;	// 0x114-0x117
	UINT32 VendorReg6;	// 0x118-0x11B
	UINT32 AhbErrSts;   	// 0x11C-0x11F
	UINT32 AhbErrEn;   	// 0x120-0x124
	UINT32 AhbErrSigEn;	// 0x124-0x127
	UINT32 DmaHndshk;	// 0x128-0x12C
	UINT32 Reserved4[19];	// 0x12C-0x177
	UINT32 VendorReg7;	// 0x178-0x17B
	UINT32 IpVersion;	// 0x17C-0x17F
	UINT32 Ciph_M_Ctl;	// 0x180-0x183
	UINT32 Ciph_M_Sts;	// 0x184-0x187
	UINT16 Ciph_M_Sts_En;	// 0x188-0x189
	UINT16 Ciph_M_Sig_En;	// 0x18A-0x18B
	UINT32 In_Data_Lo;	// 0x18C-0x18F
	UINT32 In_Data_Hi;	// 0x190-0x193
	UINT32 In_Key_Lo;	// 0x194-0x197
	UINT32 In_Key_Hi;	// 0x198-0x19B
	UINT32 Out_Data_Lo;	// 0x19C-0x19F
	UINT32 Out_Data_Hi; 	// 0x1A0-0x1A3
	UINT32 Secr_Table_Port;	// 0x1A4-0x1A7
} ftsdc021_reg;

typedef enum {
	Infinite_no = 0,
	Infinite_mode_1,	/* Block Count Reg = 2 * Desired Blocks */
	Infinite_mode_2		/* Block Count Reg = 0 */
} Infinite_Test;

typedef enum {
	WRITE = 0,
	READ
} Transfer_Act;

typedef enum {
	ADMA = 0,
	SDMA,
	PIO,
	EDMA,
	TRANS_UNKNOWN
} Transfer_Type;

/* For Asyn./ Syn abort*/
typedef enum {
	ABORT_ASYNCHRONOUS = 0,
	ABORT_SYNCHRONOUS,
	ABORT_UNDEFINED
} Abort_Type;

typedef enum {
	CPRM_PROTECT_RW,
	CPRM_FILESYS,
	CPRM_UNKNOWN
} Cprm_Test;

typedef struct {
	Transfer_Type UseDMA;	/* 0: PIO 1: SDMA 2: ADMA */
	UINT16 lineBound;
	UINT16 adma2Rand;
	Abort_Type SyncAbt;	/* 0: Async 1: Sync */
	UINT8 Erasing;		/* 0: No earsing in buruin 1:Include erase testing */
	UINT8 autoCmd;
	UINT8 Reserved;
} FlowInfo;

typedef struct {
	UINT32 Reserved1:5;	/* 508:502 */
	UINT32 SECURED_MODE:1;  /* 509 */
	UINT32 DAT_BUS_WIDTH:2; /* 511:510 */
	UINT32 SD_CARD_TYPE_HI:8; /* 495:488 */
	UINT32 Reserved2:8;	/* 501:496 */
	UINT32 SD_CARD_TYPE_LO:8; /* 487:480 */ 
	UINT32 SIZE_OF_PROTECTED_AREA; /* 479:448 */
	UINT8 SPEED_CLASS;
	UINT8 PERFORMANCE_MOVE;
	UINT32 Reserved3:4;     /* 427:424 */
	UINT32 AU_SIZE:4;       /* 431:428 */
	UINT8 ERASE_SIZE[2];   /* 423:408 */
	UINT32 ERASE_OFFSET:2;  /* 401:400 */
	UINT32 ERASE_TIMEOUT:6; /* 407:402 */
	UINT8 Reserved4[11];
	UINT8 Reserved5[39];
} SDStatus;

typedef struct {
	UINT32 CSD_STRUCTURE:2;
	UINT32 Reserved1:6;
	UINT8 TAAC;
	UINT8 NSAC;
	UINT8 TRAN_SPEED;
	UINT32 CCC:12;
	UINT32 READ_BL_LEN:4;
	UINT32 READ_BL_PARTIAL:1;
	UINT32 WRITE_BLK_MISALIGN:1;
	UINT32 READ_BLK_MISALIGN:1;
	UINT32 DSR_IMP:1;
	UINT32 Reserved2:2;
	UINT32 C_SIZE:12;
	UINT32 VDD_R_CURR_MIN:3;
	UINT32 VDD_R_CURR_MAX:3;
	UINT32 VDD_W_CURR_MIN:3;
	UINT32 VDD_W_CURR_MAX:3;
	UINT32 C_SIZE_MULT:3;
	UINT32 ERASE_BLK_EN:1;
	UINT32 SECTOR_SIZE:7;
	UINT32 WP_GRP_SIZE:7;
	UINT32 WP_GRP_ENABLE:1;
	UINT32 Reserved3:2;
	UINT32 R2W_FACTOR:3;
	UINT32 WRITE_BL_LEN:4;
	UINT32 WRITE_BL_PARTIAL:1;
	UINT32 Reserved4:5;
	UINT32 FILE_FORMAT_GRP:1;
	UINT32 COPY:1;
	UINT32 PERM_WRITE_PROTECT:1;
	UINT32 TMP_WRITE_PROTECT:1;
	UINT32 FILE_FORMAT:2;
	UINT32 Reserver5:2;

} CSD_v1;

typedef struct {
	UINT32 CSD_STRUCTURE:2;
	UINT32 Reserved1:6;
	UINT8 TAAC;
	UINT8 NSAC;
	UINT8 TRAN_SPEED;
	UINT32 CCC:12;
	UINT32 READ_BL_LEN:4;
	UINT32 READ_BL_PARTIAL:1;
	UINT32 WRITE_BLK_MISALIGN:1;
	UINT32 READ_BLK_MISALIGN:1;
	UINT32 DSR_IMP:1;
	UINT32 Reserved2:6;
	UINT32 C_SIZE:22;
	UINT32 Reserved3:1;
	UINT32 ERASE_BLK_EN:1;
	UINT32 SECTOR_SIZE:7;
	UINT32 WP_GRP_SIZE:7;
	UINT32 WP_GRP_ENABLE:1;
	UINT32 Reserved4:2;
	UINT32 R2W_FACTOR:3;
	UINT32 WRITE_BL_LEN:4;
	UINT32 WRITE_BL_PARTIAL:1;
	UINT32 Reserved5:5;
	UINT32 FILE_FORMAT_GRP:1;
	UINT32 COPY:1;
	UINT32 PERM_WRITE_PROTECT:1;
	UINT32 TMP_WRITE_PROTECT:1;
	UINT32 FILE_FORMAT:2;
	UINT32 Reserver6:2;
} CSD_v2;

// The sequence of variable in SD_SCR structure is constrained. 
typedef struct {
	UINT32 SD_SPEC:4;	/* [59:56] */
	UINT32 SCR_STRUCTURE:4;	/* [60:63] */

	UINT32 SD_BUS_WIDTHS:4;	/* [51:48] */
	UINT32 SD_SECURITY:3;	/* [52:54] */
	UINT32 DATA_STAT_AFTER_ERASE:1;	/* [55:55] */

	UINT32 Reserved1:7;	/* [46:40] */
	UINT32 SD_SPEC3:1;	/* [47:47] */

	UINT32 CMD20_SUPPORT:1;	/* [32:32] */
	UINT32 CMD23_SUPPORT:1;	/* [33:33] */
	UINT32 Reserverd2:6;	/* [34:39] */
	UINT32 Reserverd3;	/* [31:0] */

} SD_SCR;

/* for SCR */
#define SDHCI_SCR_SUPPORT_4BIT_BUS	0x4
#define SDHCI_SCR_SUPPORT_1BIT_BUS	0x1

typedef enum {
	SPEED_DEFAULT = 0,	/* or SDR12 in 1.8v IO signalling level */
	SPEED_HIGH,		/* or SDR25 in 1.8v IO signalling level */
	SPEED_SDR50,
	SPEED_SDR104,
	SPEED_DDR50,
	SPEED_RSRV
} Bus_Speed;

/* To indicate which complete we want to wait */
#define WAIT_CMD_COMPLETE   (1 << 0)
#define WAIT_TRANS_COMPLETE (1 << 1)
#define WAIT_DMA_INTR	    (1 << 2)
#define WAIT_BLOCK_GAP	    (1 << 3)

typedef struct {
	UINT32 CardInsert;
	FlowInfo FlowSet;
	UINT16 RCA;
	UINT16 DSR;
	SD_SCR SCR;
	UINT32 OCR;
	UINT64 CSD_LO;
	UINT64 CSD_HI;
	CSD_v1 CSD_ver_1;
	CSD_v2 CSD_ver_2;
	UINT64 CID_LO;
	UINT64 CID_HI;
	UINT64 respLo;
	UINT64 respHi;
	UINT32 numOfBlocks;
	UINT8 SwitchSts[64];
	volatile UINT16 ErrorSts;
	volatile UINT16 autoErr;
	volatile UINT8 cmplMask;
	SDStatus sd_status;
	UINT16 bs_mode;		/* Bus Speed Mode */
	UINT8 bus_width;
	UINT8 already_init;
	UINT8 card_init;
	UINT8 block_addr;
	UINT32 max_dtr;
	Bus_Speed speed;
	UINT32 FIFO_depth;

	/* MMC */
	//MMC_CSD CSD_MMC;
	//MMC_EXT_CSD EXT_CSD_MMC;
	UINT32 numOfBootBlocks; 
    UINT8 hpi_en;
    UINT8 hpi_cmd;
    UINT8 bkops_en;
    UINT8 R1_excep_chk;
    UINT8 packed_test_en;
    UINT8 doing_packed_cmd;
    UINT8 reliable_write_en;
    UINT8 context_id;
    UINT8 RPMB_access;

	/* SDMA */
	UINT8 u8_sdma_lock;
	UINT8 sdmaIntr;

	/* file system */
	//FileSysStruct FileSys;
	UINT32 CardType;

	/* SDIO */
	UINT8 Num_IO_Func;
	UINT8 Memory_Present;

	/* Drive Name */
	UINT32 Drive;

	/* system configurations */
	UINT32 SysFrequency;
#if 0
	/* CPRM */
	FileSysStruct Protected_FileSys;
	UINT32 Protected_Drive;
	UINT32 CPRM_Init;
	UINT32 Kmu_LO;
	UINT32 Kmu_HI;
	UINT32 AUTO_CBC;	//only used in read/write protected area
#endif

} SDCardInfo;

typedef struct {
	UINT32 max_clk;
	UINT32 min_clk;
	UINT32 clock;
	UINT8 power;
	UINT32 ocr_avail;
} SDHost;

struct mmc_data {
        Transfer_Act act;
        UINT32 *bufAddr;
        UINT32 blkCnt;
        UINT32 blkSz;
};

struct mmc_cmd {
        UINT8 CmdIndex;
        UINT8 CmdType;
        UINT8 RespType;
        UINT8 DataPresent;
        UINT8 InhibitDATChk;
        UINT32 Argu;
        struct mmc_data *data;
};                            

// Value return from Send Command function
enum {
	ERR_CMD_TIMEOUT = 1,
	ERR_NON_RECOVERABLE,
	ERR_RECOVERABLE
};

#define SDHCI_DBG

/* 0x0C: TxMode */
#define SDHCI_TXMODE_DMA_EN		(1 << 0)
#define SDHCI_TXMODE_BLKCNT_EN		(1 << 1)
#define SDHCI_TXMODE_AUTOCMD12_EN	(1 << 2)
#define SDHCI_TXMODE_AUTOCMD23_EN	(2 << 2)
#define SDHCI_TXMODE_READ_DIRECTION	(1 << 4)
#define SDHCI_TXMODE_WRITE_DIRECTION	(0 << 4)
#define SDHCI_TXMODE_MULTI_SEL		(1 << 5)

/* 0x0E: CmdReg */
/* response type: bit 0 - 4 */
#define SDHCI_CMD_NO_RESPONSE		0x0	// For no response command
#define SDHCI_CMD_RTYPE_R2		0x9	// For R2
#define SDHCI_CMD_RTYPE_R3R4		0x2	// For R3,R4
#define SDHCI_CMD_RTYPE_R1R5R6R7	0x1A	// For R1,R5,R6,R7
#define SDHCI_CMD_RTYPE_R1BR5B		0x1B	// For R1b, R5b

#define SDHCI_CMD_TYPE_NORMAL		0x0
#define SDHCI_CMD_TYPE_SUSPEND		0x1
#define SDHCI_CMD_TYPE_RESUME		0x2
#define SDHCI_CMD_TYPE_ABORT		0x3

#define SDHCI_CMD_DATA_PRESENT		0x1

/* 0x20: Buf data port*/
#define SDHCI_DATA_PORT			0x20

/* 0x24: Present State Register */
#define SDHCI_Pre_State			0x24
#define SDHCI_STS_CMD_INHIBIT		(1 << 0)
#define SDHCI_STS_CMD_DAT_INHIBIT	(1 << 1)
#define SDHCI_STS_DAT_LINE_ACT		(1 << 2)
#define SDHCI_STS_WRITE_TRAN_ACT	(1 << 8)
#define SDHCI_STS_READ_TRAN_ACT		(1 << 9)
#define SDHCI_STS_BUFF_WRITE		(1 << 10)
#define SDHCI_STS_BUFF_READ		(1 << 11)
#define SDHCI_STS_CARD_INSERT		(1 << 16)
#define SDHCI_STS_CARD_STABLE		(1 << 17)
#define SDHCI_STS_DAT_LINE_LEVEL	(0xF << 20)
#define SDHCI_STS_CMD_LINE_LEVEL	(1 << 24)

/* 0x28: HCReg */
#define SDHCI_HC_LED_ON			(1 << 0)
#define SDHCI_HC_BUS_WIDTH_4BIT		(1 << 1)
#define SDHCI_HC_HI_SPEED		(1 << 2)
#define SDHCI_HC_USE_ADMA2		(2 << 3)
#define SDHCI_HC_BUS_WIDTH_8BIT		(1 << 5)
#define SDHCI_HC_CARD_DETECT_TEST	(1 << 6)
#define SDHCI_HC_CARD_DETECT_SIGNAL	(1 << 7)

/* 0x29: */
#define SDHCI_POWER_ON			(1 << 0)
#define SDHCI_POWER_180			(5 << 1)
#define SDHCI_POWER_300			(6 << 1)
#define SDHCI_POWER_330			(7 << 1)

/* 0x2A: BlkGapCtl*/
#define SDHCI_STOP_AT_BLOCK_GAP_REQ 	(1 << 0)
#define SDHCI_CONTINUE_REQ		(1 << 1)
#define SDHCI_READ_WAIT_CTL		(1 << 2)
#define SDHCI_INT_AT_BLOCK_GAP		(1 << 3)

/* 0x2C: ClkCntl */
#define SDHCI_CLKCNTL_INTERNALCLK_EN	(1 << 0)
#define SDHCI_CLKCNTL_INTERNALCLK_STABLE	(1 << 1)
#define SDHCI_CLKCNTL_SDCLK_EN		(1 << 2)

/* 0x2F: SoftRst */
#define SDHCI_SOFTRST_ALL		(1 << 0)
#define SDHCI_SOFTRST_CMD		(1 << 1)
#define SDHCI_SOFTRST_DAT		(1 << 2)

/* 0x30: IntrSts */
#define SDHCI_INTR_State		0x30
#define SDHCI_INTR_STS_ERR		(1 << 15)
#define SDHCI_INTR_STS_CARD_INTR	(1 << 8)
#define SDHCI_INTR_STS_CARD_REMOVE	(1 << 7)
#define SDHCI_INTR_STS_CARD_INSERT	(1 << 6)
#define SDHCI_INTR_STS_BUFF_READ_READY	(1 << 5)
#define SDHCI_INTR_STS_BUFF_WRITE_READY	(1 << 4)
#define SDHCI_INTR_STS_DMA		(1 << 3)
#define SDHCI_INTR_STS_BLKGAP		(1 << 2)
#define SDHCI_INTR_STS_TXR_COMPLETE	(1 << 1)
#define SDHCI_INTR_STS_CMD_COMPLETE	(1 << 0)

/* 0x32: ErrSts */
#define SDHCI_INTR_ERR_TUNING		(1 << 10)
#define SDHCI_INTR_ERR_ADMA		(1 << 9)
#define SDHCI_INTR_ERR_AutoCMD		(1 << 8)
#define SDHCI_INTR_ERR_CURR_LIMIT	(1 << 7)
#define SDHCI_INTR_ERR_DATA_ENDBIT	(1 << 6)
#define SDHCI_INTR_ERR_DATA_CRC		(1 << 5)
#define SDHCI_INTR_ERR_DATA_TIMEOUT	(1 << 4)
#define SDHCI_INTR_ERR_CMD_INDEX	(1 << 3)
#define SDHCI_INTR_ERR_CMD_ENDBIT	(1 << 2)
#define SDHCI_INTR_ERR_CMD_CRC		(1 << 1)
#define SDHCI_INTR_ERR_CMD_TIMEOUT	(1 << 0)
#define SDHCI_INTR_ERR_CMD_LINE		(SDHCI_INTR_ERR_CMD_INDEX | SDHCI_INTR_ERR_CMD_ENDBIT | SDHCI_INTR_ERR_CMD_CRC | SDHCI_INTR_ERR_CMD_TIMEOUT)
#define SDHCI_INTR_ERR_DAT_LINE		(SDHCI_INTR_ERR_DATA_ENDBIT | SDHCI_INTR_ERR_DATA_CRC | SDHCI_INTR_ERR_DATA_TIMEOUT)

/* 0x34: IntrEn */
#define SDHCI_INTR_EN_ALL		(0x10FF)

/* 0x36: ErrEn */
#define SDHCI_ERR_EN_ALL		(0xF7FF)

/* 0x38: IntrSigEn */
//#define SDHCI_INTR_SIG_EN_ALL           (0xF0CC)
//#define SDHCI_INTR_SIG_EN             (0x10CC)
#define SDHCI_INTR_SIG_EN (SDHCI_INTR_STS_CARD_REMOVE | SDHCI_INTR_STS_CARD_INSERT | SDHCI_INTR_STS_CMD_COMPLETE | SDHCI_INTR_STS_TXR_COMPLETE)
#define SDHCI_INTR_SIGN_EN_SDMA (SDHCI_INTR_SIG_EN | SDHCI_INTR_STS_DMA | SDHCI_INTR_STS_BLKGAP)
#define SDHCI_INTR_SIGN_EN_ADMA (SDHCI_INTR_SIG_EN | SDHCI_INTR_STS_DMA)
#define SDHCI_INTR_SIGN_EN_PIO (SDHCI_INTR_SIG_EN | SDHCI_INTR_STS_BLKGAP)

/* 0x3A: ErrSigEn */
//#define SDHCI_ERR_SIG_EN_ALL            (0xF2FF)
#define SDHCI_ERR_SIG_EN_ALL		(0xF3FF)

/* 0x3C: AutoCMD12 Err */
#define SDHCI_AUTOCMD12_ERR_NOT_EXECUTED 	(1 << 0)
#define SDHCI_AUTOCMD12_ERR_TIMEOUT		(1 << 1)
#define SDHCI_AUTOCMD12_ERR_CRC			(1 << 2)
#define SDHCI_AUTOCMD12_ERR_END_BIT		(1 << 3)
#define SDHCI_AUTOCMD12_ERR_INDEX		(1 << 4)
#define SDHCI_AUTOCMD12_ERR_CMD_NOT_ISSUE	(1 << 7)

/* 0x3E: Host Control 2 */
#define SDHCI_HOST_CONTROL2     0x3E
#define  SDHCI_PRESET_VAL_EN    (1 << 15)
#define  SDHCI_ASYNC_INT_EN     (1 << 14)
#define  SDHCI_SMPL_CLCK_SELECT (1 << 7)
#define  SDHCI_EXECUTE_TUNING   (1 << 6)	/* Write 1 Auto clear */
#define  SDHCI_DRV_TYPE_MASK    (3 << 4)
#define  SDHCI_DRV_TYPE_SHIFT   4
#define   SDHCI_DRV_TYPEB	0
#define   SDHCI_DRV_TYPEA	1
#define   SDHCI_DRV_TYPEC       2
#define   SDHCI_DRV_TYPED 	3
#define  SDHCI_18V_SIGNAL       (1 << 3)
#define  SDHCI_UHS_MODE_MASK    (7 << 0)
#define   SDHCI_SDR12           0
#define   SDHCI_SDR25           1
#define   SDHCI_SDR50           2
#define   SDHCI_SDR104          3
#define   SDHCI_DDR50           4

/* 0x40: Capabilities */
#define SDHCI_CAP_VOLTAGE_33V		(1 << 24)
#define SDHCI_CAP_VOLTAGE_30V		(1 << 25)
#define SDHCI_CAP_VOLTAGE_18V		(1 << 26)
#define SDHCI_CAP_FIFO_DEPTH_16BYTE	(0 << 29)
#define SDHCI_CAP_FIFO_DEPTH_32BYTE	(1 << 29)
#define SDHCI_CAP_FIFO_DEPTH_64BYTE	(2 << 29)
#define SDHCI_CAP_FIFO_DEPTH_512BYTE	(3 << 29)
#define SDHCI_CAP_FIFO_DEPTH_1024BYTE	(4 << 29)
#define SDHCI_CAP_FIFO_DEPTH_2048BYTE	(5 << 29)

/*BingJiun: 0x44 - 0x47 */
#define  SDHCI_SUPPORT_SDR50    	(1 << 0)
#define  SDHCI_SUPPORT_SDR104   	(1 << 1)
#define  SDHCI_SUPPORT_DDR50    	(1 << 2)
#define  SDHCI_SUPPORT_DRV_TYPEA        (1 << 4)
#define  SDHCI_SUPPORT_DRV_TYPEC        (1 << 5)
#define  SDHCI_SUPPORT_DRV_TYPED        (1 << 6)
#define  SDHCI_RETUNING_TIME_MASK       0xF
#define  SDHCI_RETUNING_TIME_SHIFT      8
#define  SDHCI_SDR50_TUNING     	(1 << 13)
#define  SDCHI_RETUNING_MODE_MASK     	0x3
#define  SDHCI_RETUNING_MODE_SHIFT      14

/* Vendor Defined0(0x100) */
/* Vendor Defined1(0x104) */
#define MMC_BOOT_ACK			(1 << 2)
#define MMC_BUS_TEST_MODE		0x3
#define MMC_ALTERNATIVE_BOOT_MODE	0x2
#define MMC_BOOT_MODE			0x1
#define NORMAL_MODE			0x0
/* Vendor Defined2(0x108) */
/* Vendor Defined3(0x10C) */

#define SDHCI_GO_IDLE_STATE		0
#define MMC_SEND_OP_COND		1
#define SDHCI_SEND_ALL_CID		2
#define SDHCI_SEND_RELATIVE_ADDR	3
#define SDHCI_IO_SEND_OP_COND		5
#define MMC_SWITCH			6 
#define SDHCI_SWITCH_FUNC		6
#define SDHCI_SET_BUS_WIDTH		6
#define SDHCI_SELECT_CARD		7
#define SDHCI_SEND_IF_COND		8
#define MMC_SEND_EXT_CSD		8
#define SDHCI_SEND_CSD			9
#define SDHCI_SEND_CID			10
#define SDHCI_VOLTAGE_SWITCH		11
#define SDHCI_STOP_TRANS		12
#define SDHCI_SEND_STATUS		13
#define SDHCI_SD_STATUS			13
#define SDHCI_SET_BLOCKLEN		16
#define SDHCI_READ_SINGLE_BLOCK		17
#define SDHCI_READ_MULTI_BLOCK		18
#define SDHCI_SEND_TUNE_BLOCK		19
//#define SDHCI_SET_WR_BLOCK_CNT		23
#define MMC_SEND_TUNE_BLOCK		21
#define SDHCI_SEND_NUM_WR_BLKS		22
#define SDHCI_SET_BLOCK_COUNT		23
#define SDHCI_WRITE_BLOCK		24
#define SDHCI_WRITE_MULTI_BLOCK		25

#define SDHCI_SET_WRITE_PROT            28
#define SDHCI_CLR_WRITE_PROT            29
#define SDHCI_SEND_WRITE_PROT           30
#define SDHCI_SEND_WRITE_PROT_TYPE      31

#define SDHCI_ERASE_WR_BLK_START	32
#define SDHCI_ERASE_WR_BLK_END		33
#define SDHCI_ERASE_GROUP_START		35
#define SDHCI_ERASE_GROUP_END		36
#define SDHCI_ERASE			38
#define SDHCI_SD_SEND_OP_COND		41
/* Legend added */
#define SDHCI_SD_CLR_CARD_DETECT		42
#define SDHCI_GET_MKB			43
#define SDHCI_GET_MID			44
#define SDHCI_CER_RN1			45
#define SDHCI_CER_RN2			46
#define SDHCI_CER_RES2			47
#define SDHCI_CER_RES1			48
#define MMC_SET_TIME			49 
#define SDHCI_SEND_SCR			51
#define SDHCI_IO_RW_DIRECT		52
#define SDHCI_IO_RW_EXTENDED		53
#define SDHCI_APP_CMD			55
#define SDHCI_GEN_CMD			56
#define SD_CMD_READ_OCR			58
#define MMC_VENDOR_CMD			62 

#define SDHCI_SEND_IF_COND_ARGU			0x1AA
#define SDHCI_SD_SEND_OP_COND_HCS_ARGU		0xC0FF8000
#define SDHCI_SD_SEND_OP_COND_ARGU		0x00FF8000
#define SDHCI_MMC_SEND_OP_COND_BYTE_MODE	0x80FF8000
#define SDHCI_MMC_SEND_OP_COND_SECTOR_MODE	0xC0FF8000

#define CMD_RETRY_CNT		5
#define SDHCI_TIMEOUT		0xFFF

/* SD state diagram */
/*#define SD_CID_MODE		0x1
#define SD_STANDBY_STATE	0x2
#define SD_TRANSFER_STATE	0x3
#define SD_SND_DATA_STATE	0x4
#define SD_RCV_DATA_STATE	0x5
#define SD_PROGRAM_STATE	0x6
#define SD_DISCONNECT_STATE	0x7
*/

/* For CMD52*/
#define SD_CMD52_RW_in_W		0x80000000
#define SD_CMD52_RW_in_R		0x00000000
#define SD_CMD52_RAW			0x08000000
#define SD_CMD52_no_RAW			0x00000000
#define SD_CMD52_FUNC(Num)		(Num  << 28)
#define SD_CMD52_Reg_Addr(Addr) (Addr << 9)
/* For CMD53*/
#define SD_CMD53_RW_in_W		0x80000000
#define SD_CMD53_RW_in_R		0x00000000
#define SD_CMD53_FUNC(Num)		(Num  << 28)
#define SD_CMD53_Block_Mode		0x08000000
#define SD_CMD53_Byte_Mode		0x00000000
#define SD_CMD53_OP_inc			0x04000000
#define SD_CMD53_OP_fix			0x00000000
#define SD_CMD53_Reg_Addr(Addr) (Addr << 9)
//************************************

/**
 * Card status return from R1 response format.
 * Or use CMD13 to get this status 
 */
#define SD_STATUS_OUT_OF_RANGE        0x80000000
#define SD_STATUS_ADDRESS_ERROR       (1 << 30)
#define SD_STATUS_BLOCK_LEN_ERROR     (1 << 29)
#define SD_STATUS_ERASE_SEQ_ERROR     (1 << 28)
#define SD_STATUS_ERASE_PARAM         (1 << 27)
#define SD_STATUS_WP_VIOLATION        (1 << 26)
#define SD_STATUS_CARD_IS_LOCK        (1 << 25)
#define SD_STATUS_LOCK_UNLOCK_FAILED  (1 << 24)
#define SD_STATUS_COM_CRC_ERROR       (1 << 23)
#define SD_STATUS_ILLEGAL_COMMAND     (1 << 22)
#define SD_STATUS_CARD_ECC_FAILED     (1 << 21)
#define SD_STATUS_CC_ERROR            (1 << 20)
#define SD_STATUS_ERROR               (1 << 19)
#define SD_STATUS_UNDERRUN            (1 << 18)
#define SD_STATUS_OVERRUN             (1 << 17)
#define SD_STATUS_CSD_OVERWRITE       (1 << 16)
#define SD_STATUS_WP_ERASE_SKIP       (1 << 15)
#define SD_STATUS_CARD_ECC_DISABLE    (1 << 14)
#define SD_STATUS_ERASE_RESET         (1 << 13)
#define SD_STATUS_CURRENT_STATE(x)    ((x >> 9) & 0xF )
typedef enum {
	CUR_STATE_IDLE = 0,
	CUR_STATE_READY,
	CUR_STATE_IDENT,
	CUR_STATE_STBY,
	CUR_STATE_TRAN,
	CUR_STATE_DATA,
	CUR_STATE_RCV,
	CUR_STATE_PRG,
	CUR_STATE_DIS,
	CUR_STATE_RSV
} Card_State;

#define SD_STATUS_READY_FOR_DATA      (1 << 8)
#define MMC_STATUS_SWITCH_ERROR       (1 << 7)
#define SD_STATUS_APP_CMD             (1 << 5)
#define SD_STATUS_AKE_SEQ_ERROR       (1 << 3)

#define SD_STATUS_ERROR_BITS          (SD_STATUS_OUT_OF_RANGE | SD_STATUS_ADDRESS_ERROR | \
                                       SD_STATUS_BLOCK_LEN_ERROR | SD_STATUS_ERASE_SEQ_ERROR | \
                                       SD_STATUS_ERASE_PARAM | SD_STATUS_WP_VIOLATION | \
                                       SD_STATUS_LOCK_UNLOCK_FAILED | SD_STATUS_CARD_ECC_FAILED | \
                                       SD_STATUS_CC_ERROR | SD_STATUS_ERROR | \
                                       SD_STATUS_UNDERRUN | SD_STATUS_OVERRUN | \
                                       SD_STATUS_CSD_OVERWRITE | SD_STATUS_WP_ERASE_SKIP | \
                                       SD_STATUS_AKE_SEQ_ERROR | MMC_STATUS_SWITCH_ERROR)

#define SDHCI_1BIT_BUS_WIDTH	0x0
#define SDHCI_4BIT_BUS_WIDTH	0x2

/* ADMA Descriptor Table Generator */
#define ADMA2_ENTRY_VALID	(1 << 0)
#define ADMA2_ENTRY_END		(1 << 1)
#define ADMA2_ENTRY_INT		(1 << 2)

#define ADMA2_NOP		(0 << 4)
#define ADMA2_SET		(1 << 4)
#define ADMA2_TRAN		(2 << 4)
#define ADMA2_LINK		(3 << 4)

typedef struct {
	UINT16 attr;
	UINT16 lgth;
	UINT32 addr;
} Adma2DescTable;

/* ftsdc021_main.c */
UINT8 *SDC_ShowCardState(Card_State state);
#ifdef SDHCI_DEBUG
void SDC_ShowDscpTbl(UINT32 blkcnt, UINT32 tbl_addr);
#endif

/* ftsdc021_ops.c */
/**
 * SDIO card related operations
 */
UINT32 ftsdc021_ops_send_io_op_cond(SDCardInfo * card, UINT32 ocr, UINT32 * rocr);
UINT32 ftsdc021_io_rw_direct(SDCardInfo * card, UINT32 write, UINT8 fn, UINT32 addr, UINT8 in, UINT8 * out);
UINT32 ftsdc021_io_rw_extended(SDCardInfo * card, UINT32 write, UINT8 fn, UINT32 addr, UINT32 incr_addr, UINT32 * buf,
			       UINT32 blocks, UINT32 blksz);
UINT32 ftsdc021_sdio_set_bus_width(SDCardInfo * card, UINT32 width);
UINT32 ftsdc021_sdio_set_bus_speed(SDCardInfo * card, UINT8 speed);
UINT32 ftsdc021_ops_Card_Info(void);

/**
 * MMC card related operations
 */
UINT32 ftsdc021_ops_send_op_cond(SDCardInfo * card, UINT32 ocr, UINT32 * rocr);
UINT32 ftsdc021_ops_mmc_switch(SDCardInfo * card, UINT8 set, UINT8 index, UINT8 value);
UINT32 ftsdc021_ops_send_ext_csd(SDCardInfo * card);
UINT32 ftsdc021_ops_set_write_prot(SDCardInfo * card, UINT32 address);   
UINT32 ftsdc021_ops_clear_write_prot(SDCardInfo * card, UINT32 address);
UINT32 ftsdc021_ops_send_write_prot(SDCardInfo * card, UINT32 * WP_bits, UINT32 length);
UINT32 ftsdc021_ops_send_write_prot_type(SDCardInfo * card, UINT32 * WP_bits, UINT32 length);
/**
 * SD card related operations(Some applies to MMC)
 */
UINT32 ftsdc021_ops_go_idle_state(UINT32 arg);
UINT32 ftsdc021_ops_send_if_cond(SDCardInfo * card, UINT32 arg);
UINT32 ftsdc021_ops_send_app_op_cond(SDCardInfo * card, UINT32 ocr, UINT32 * rocr);
// ACMD42
UINT32 ftsdc021_ops_app_set_clr_cd(SDCardInfo * card, UINT32 value);
UINT32 ftsdc021_ops_send_voltage_switch(void);
UINT32 ftsdc021_ops_all_send_cid(SDCardInfo * card);
UINT32 ftsdc021_ops_send_rca(SDCardInfo * card);
UINT32 ftsdc021_ops_send_csd(SDCardInfo * card);
UINT32 ftsdc021_ops_select_card(SDCardInfo * card);
UINT32 ftsdc021_ops_app_send_scr(SDCardInfo * card);
UINT32 ftsdc021_ops_app_repo_wr_num(SDCardInfo * card, UINT32 *written_num);
UINT32 ftsdc021_ops_app_set_wr_blk_cnt(SDCardInfo * card, UINT32 n_blocks);
UINT32 ftsdc021_ops_app_set_bus_width(SDCardInfo * card, UINT32 width);
UINT32 ftsdc021_ops_sd_switch(SDCardInfo * card, UINT32 mode, UINT32 group, UINT8 value, UINT8 * resp);
UINT32 ftsdc021_ops_send_tune_block(SDCardInfo * card);
UINT32 ftsdc021_ops_send_card_status(SDCardInfo * card);
UINT32 ftsdc021_ops_set_blocklen(SDCardInfo * card, UINT32 block_len);
UINT32 ftsdc021_ops_send_sd_status(SDCardInfo * card);

/* ftsdc021.c */
BOOL ftsdc021_fill_adma_desc_table(UINT32 total_data, UINT32 data_addr);
void ftsdc021_delay(UINT32 ms);
UINT32 ftsdc021_send_data_command(Transfer_Act act, UINT32 startAddr, UINT32 blkCnt, UINT32 blkSz, UINT32 * bufAddr);
UINT32 ftsdc021_send_vendor_cmd(UINT32 argument);
UINT32 ftsdc021_transfer_data(Transfer_Act act, UINT32 * buffer, UINT32 length);
UINT32 ftsdc021_CheckCardInsert(void);
void ftsdc021_SetPower(INT16 power);
void ftsdc021_SetSDClock(UINT32 clock);
UINT32 ftsdc021_set_partition_access(UINT8 partition);
UINT32 ftsdc021_set_bootmode(UINT8 partition);
UINT32 ftsdc021_set_bootack(UINT8 ack); 
UINT32 ftsdc021_do_hpi(void);
UINT32 ftsdc021_pulselatch_tuning_1(void);
UINT32 ftsdc021_pulselatch_tuning(UINT32 div);
UINT32 ftsdc021_gen_packed_hdr(Transfer_Act act, UINT32 startAddr, UINT32 blkcnt, UINT32 * buf);
UINT32 ftsdc021_set_boot_size(UINT8 value);
UINT32 ftsdc021_set_bus_width(UINT8 width);
UINT32 ftsdc021_set_bus_speed_mode(UINT8 speed);
UINT32 ftsdc021_read_scr(void);
UINT32 ftsdc021_read_ext_csd(void);
UINT32 ftsdc021_uhs1_mode(void);
UINT32 ftsdc021_signal_voltage_switch(void);
UINT32 ftsdc021_execute_tuning(UINT32 try);
void ftsdc021_set_base_clock(UINT32 clk);
void ftsdc021_set_transfer_type(Transfer_Type type, UINT32 line_bound, UINT8 ran_mode);
void ftsdc021_HCReset(UINT8 type);
UINT32 ftsdc021_wait_for_state(UINT32 state, UINT32 ms);
UINT32 ftsdc021_prepare_data(UINT32 blk_cnt, UINT16 blk_sz, UINT32 buff_addr, Transfer_Act act);
UINT32 ftsdc021_set_transfer_mode(UINT8 blk_cnt_en, UINT8 auto_cmd, UINT8 dir, UINT8 multi_blk);
UINT32 ftsdc021_send_abort_command(void);
UINT32 ftsdc021_send_command(struct mmc_cmd *mcmd);
UINT32 ftsdc021_card_read(UINT32 startAddr, UINT32 blkcnt, UINT8 * read_buf);
UINT32 ftsdc021_card_write(UINT32 startAddr, UINT32 blkcnt, UINT8 * write_buf);
UINT32 get_erase_group_size(UINT32 * erase_group_size);
UINT32 ftsdc021_card_erase(UINT32 StartBlk, UINT32 BlkCount);
UINT32 ftsdc021_Abort_test(UINT8 * read_buf, UINT8 * write_buf, UINT32 blk_cnt);
UINT32 ftsdc021_boot(UINT8 boot_mode, UINT8 ack, UINT8 boot_spd, UINT8 boot_bw, UINT32 boot_addr, UINT32 boot_blocks);
UINT32 ftsdc021_scan_cards(UINT8 boot_mode);
UINT32 ftsdc021_init(void);

UINT32 SDC_data_check(UINT32 blkcnt, UINT32 * source_buf, UINT32 * dest_buf);
void SDC_PrepareWB(UINT32 length);

extern SDCardInfo cardInfo;
static inline UINT32 u32ReadHCLK(void) { return 100000000; }

#endif
